package file;


import java.io.File;
import java.io.FileFilter;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.Reader;
import java.math.BigInteger;
import java.net.URL;
import java.nio.charset.Charset;
import java.util.Collection;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.zip.Checksum;

import org.apache.commons.io.FileExistsException;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.io.LineIterator;
import org.apache.commons.io.filefilter.IOFileFilter;

/**
 * General file manipulation utilities.
 * <p>
 * Facilities are provided in the following areas:
 * <ul>
 * <li>writing to a file
 * <li>reading from a file
 * <li>make a directory including parent directories
 * <li>copying files and directories
 * <li>deleting files and directories
 * <li>converting to and from a URL
 * <li>listing files and directories by filter and extension
 * <li>comparing file content
 * <li>file last changed date
 * <li>calculating a checksum
 * </ul>
 * <p>
 * Origin of code: Excalibur, Alexandria, Commons-Utils
 *
 * @version $Id: FileUtils.java 1722481 2016-01-01 01:42:04Z dbrosius $
 */
public class FileUtil {

    /**
     * The number of bytes in a kilobyte.
     */
    public static final long ONE_KB = 1024;

    /**
     * The number of bytes in a kilobyte.
     *
     * @since 2.4
     */
    public static final BigInteger ONE_KB_BI = BigInteger.valueOf(ONE_KB);

    /**
     * The number of bytes in a megabyte.
     */
    public static final long ONE_MB = ONE_KB * ONE_KB;

    /**
     * The number of bytes in a megabyte.
     *
     * @since 2.4
     */
    public static final BigInteger ONE_MB_BI = ONE_KB_BI.multiply(ONE_KB_BI);

    /**
     * The file copy buffer size (30 MB)
     */
    private static final long FILE_COPY_BUFFER_SIZE = ONE_MB * 30;

    /**
     * The number of bytes in a gigabyte.
     */
    public static final long ONE_GB = ONE_KB * ONE_MB;

    /**
     * The number of bytes in a gigabyte.
     *
     * @since 2.4
     */
    public static final BigInteger ONE_GB_BI = ONE_KB_BI.multiply(ONE_MB_BI);

    /**
     * The number of bytes in a terabyte.
     */
    public static final long ONE_TB = ONE_KB * ONE_GB;

    /**
     * The number of bytes in a terabyte.
     *
     * @since 2.4
     */
    public static final BigInteger ONE_TB_BI = ONE_KB_BI.multiply(ONE_GB_BI);

    /**
     * The number of bytes in a petabyte.
     */
    public static final long ONE_PB = ONE_KB * ONE_TB;

    /**
     * The number of bytes in a petabyte.
     *
     * @since 2.4
     */
    public static final BigInteger ONE_PB_BI = ONE_KB_BI.multiply(ONE_TB_BI);

    /**
     * The number of bytes in an exabyte.
     */
    public static final long ONE_EB = ONE_KB * ONE_PB;

    /**
     * The number of bytes in an exabyte.
     *
     * @since 2.4
     */
    public static final BigInteger ONE_EB_BI = ONE_KB_BI.multiply(ONE_PB_BI);

    /**
     * The number of bytes in a zettabyte.
     */
    public static final BigInteger ONE_ZB = BigInteger.valueOf(ONE_KB).multiply(BigInteger.valueOf(ONE_EB));

    /**
     * The number of bytes in a yottabyte.
     */
    public static final BigInteger ONE_YB = ONE_KB_BI.multiply(ONE_ZB);

    /**
     * An empty array of type <code>File</code>.
     */
    public static final File[] EMPTY_FILE_ARRAY = new File[0];

    //-----------------------------------------------------------------------
    /**
     * 从一组名称元素构建一个文件。
     *
     * @param directory the parent directory
     * @param names the name elements
     * @return the file
     * @since 2.1
     */
    public static File getFile(final File directory, final String... names) {
        return FileUtils.getFile(directory, names);
    }

    /**
     * 从一组名称元素构建一个文件。
     *
     * @param names the name elements
     * @return the file
     * @since 2.1
     */
    public static File getFile(final String... names) {
        return FileUtils.getFile(names);
    }

    /**
     * 返回系统临时目录的路径。
     *
     * @return the path to the system temporary directory.
     *
     * @since 2.0
     */
    public static String getTempDirectoryPath() {
    	return FileUtils.getTempDirectoryPath();
    }

    /**
     * 返回一个File表示系统临时目录。
     *
     * @return the system temporary directory.
     *
     * @since 2.0
     */
    public static File getTempDirectory() {
        return FileUtils.getTempDirectory();
    }

    /**
     * 返回File代表用户的主目录。
     *
     * @return the path to the user's home directory.
     *
     * @since 2.0
     */
    public static String getUserDirectoryPath() {
        return FileUtils.getUserDirectoryPath();
    }

    /**
     * 返回用户主目录的路径。
     *
     * @return the user's home directory.
     *
     * @since 2.0
     */
    public static File getUserDirectory() {
        return FileUtils.getUserDirectory();
    }

    //-----------------------------------------------------------------------
    /**
     * 打开一个FileInputStream指定的文件，提供比简单调用更好的错误信息
     * 
     * @param file the file to open for input, must not be {@code null}
     * @return a new {@link FileInputStream} for the specified file
     * @throws FileNotFoundException if the file does not exist
     * @throws IOException           if the file object is a directory
     * @throws IOException           if the file cannot be read
     * @since 1.3
     */
    public static FileInputStream openInputStream(final File file) throws IOException {
        return FileUtils.openInputStream(file);
    }

    //-----------------------------------------------------------------------
    /**
     * 打开FileOutputStream指定文件，检查并创建父目录（如果不存在）
     *
     * @param file the file to open for output, must not be {@code null}
     * @return a new {@link FileOutputStream} for the specified file
     * @throws IOException if the file object is a directory
     * @throws IOException if the file cannot be written to
     * @throws IOException if a parent directory needs creating but that fails
     * @since 1.3
     */
    public static FileOutputStream openOutputStream(final File file) throws IOException {
        return FileUtils.openOutputStream(file);
    }

    /**
     * 打开FileOutputStream指定文件，检查并创建父目录（如果不存在）
     *
     * @param file   the file to open for output, must not be {@code null}
     * @param append if {@code true}, then bytes will be added to the
     *               end of the file rather than overwriting
     * @return a new {@link FileOutputStream} for the specified file
     * @throws IOException if the file object is a directory
     * @throws IOException if the file cannot be written to
     * @throws IOException if a parent directory needs creating but that fails
     * @since 2.1
     */
    public static FileOutputStream openOutputStream(final File file, final boolean append) throws IOException {
        return FileUtils.openOutputStream(file, append);
    }

    //-----------------------------------------------------------------------
    /**
		 返回文件大小的可读版本，其中输入表示特定的字节数。
		如果大小超过1GB，大小将返回为整个GB的数量，即将大小向下舍入到最接近的GB边界。
     *
     * @param size the number of bytes
     * @return a human-readable display value (includes units - EB, PB, TB, GB, MB, KB or bytes)
     * @see <a href="https://issues.apache.org/jira/browse/IO-226">IO-226 - should the rounding be changed?</a>
     * @since 2.4
     */
    // See https://issues.apache.org/jira/browse/IO-226 - should the rounding be changed?
    public static String byteCountToDisplaySize(final BigInteger size) {
        return FileUtils.byteCountToDisplaySize(size);
    }

    /**
     * 返回文件大小的可读版本，其中输入表示特定的字节数。
	         如果大小超过1GB，大小将返回为整个GB的数量，即将大小向下舍入到最接近的GB边界。
     *
     * @param size the number of bytes
     * @return a human-readable display value (includes units - EB, PB, TB, GB, MB, KB or bytes)
     * @see <a href="https://issues.apache.org/jira/browse/IO-226">IO-226 - should the rounding be changed?</a>
     */
    // See https://issues.apache.org/jira/browse/IO-226 - should the rounding be changed?
    public static String byteCountToDisplaySize(final long size) {
        return FileUtils.byteCountToDisplaySize(size);
    }

    //-----------------------------------------------------------------------
    /**
     * 实现与Unix上的“touch”实用程序相同的行为。它会创建一个大小为0的新文件，如果该文件已经存在，则将其打开并关闭而不修改它，但会更新文件日期和时间。
		注意：从v1.3开始，如果无法设置文件的最后修改日期，则此方法将抛出IOException。另外，从v1.3开始，如果这个方法不存在，这个方法会创建父目录
     * @param file the File to touch
     * @throws IOException If an I/O problem occurs
     */
    public static void touch(final File file) throws IOException {
    	FileUtils.touch(file);
    }

    //-----------------------------------------------------------------------
    /**
     * 将包含java.io.File的Collection转换为数组表示形式。这是为了解决File.listFiles（）和FileUtils.listFiles（）之间的差异。
     *
     * @param files a Collection containing java.io.File instances
     * @return an array of java.io.File
     */
    public static File[] convertFileCollectionToFileArray(final Collection<File> files) {
        return FileUtils.convertFileCollectionToFileArray(files);
    }

    /**
     * 在给定的目录（及其可选的子目录）中查找文件。找到的所有文件都由IOFileFilter过滤。
	           如果你的搜索应该递归到子目录中，你可以通过一个IOFileFilter来传递目录。您不需要将DirectoryFileFilter（通过逻辑AND）绑定到此过滤器。这个方法为你做。
		一个例子：如果你想搜索所有名为“temp”的目录，你传入 FileFilterUtils.NameFileFilter("temp")
		此方法的另一个常见用法是在目录树中查找文件，但忽略生成的CVS目录。你可以简单地传递FileFilterUtils.makeCVSAware(null)。
     * @return an collection of java.io.File with the matching files
     * @see org.apache.commons.io.filefilter.FileFilterUtils
     * @see org.apache.commons.io.filefilter.NameFileFilter
     */
    public static Collection<File> listFiles(
            final File directory, final IOFileFilter fileFilter, final IOFileFilter dirFilter) {
        return FileUtils.listFiles(directory, fileFilter, dirFilter);
    }

    /**
     * 在给定的目录（及其可选的子目录）中查找文件。找到的所有文件都由IOFileFilter过滤。
		生成的集合包括起始目录和与目录过滤器匹配的所有子目录。
     *
     * @param directory  the directory to search in
     * @param fileFilter filter to apply when finding files.
     * @param dirFilter  optional filter to apply when finding subdirectories.
     *                   If this parameter is {@code null}, subdirectories will not be included in the
     *                   search. Use TrueFileFilter.INSTANCE to match all directories.
     * @return an collection of java.io.File with the matching files
     * @see org.apache.commons.io.FileUtils#listFiles
     * @see org.apache.commons.io.filefilter.FileFilterUtils
     * @see org.apache.commons.io.filefilter.NameFileFilter
     * @since 2.2
     */
    public static Collection<File> listFilesAndDirs(
            final File directory, final IOFileFilter fileFilter, final IOFileFilter dirFilter) {
        return FileUtils.listFilesAndDirs(directory, fileFilter, dirFilter);
    }

    /**
     * 允许迭代给定目录中的文件（以及可选的子目录）。
		找到的所有文件都由IOFileFilter过滤。这个方法基于listFiles(File, IOFileFilter, IOFileFilter)，支持Iterable（'foreach'循环）。

     * @param directory  the directory to search in
     * @param fileFilter filter to apply when finding files.
     * @param dirFilter  optional filter to apply when finding subdirectories.
     *                   If this parameter is {@code null}, subdirectories will not be included in the
     *                   search. Use TrueFileFilter.INSTANCE to match all directories.
     * @return an iterator of java.io.File for the matching files
     * @see org.apache.commons.io.filefilter.FileFilterUtils
     * @see org.apache.commons.io.filefilter.NameFileFilter
     * @since 1.2
     */
    public static Iterator<File> iterateFiles(
            final File directory, final IOFileFilter fileFilter, final IOFileFilter dirFilter) {
        return FileUtils.iterateFiles(directory, fileFilter, dirFilter);
    }

    /**
     * 允许迭代给定目录中的文件（以及可选的子目录）。
	找到的所有文件都由IOFileFilter过滤。这个方法基于listFilesAndDirs(File, IOFileFilter, IOFileFilter)，支持Iterable（'foreach'循环）。
	
	生成的迭代器本身包含子目录。
     *
     * @param directory  the directory to search in
     * @param fileFilter filter to apply when finding files.
     * @param dirFilter  optional filter to apply when finding subdirectories.
     *                   If this parameter is {@code null}, subdirectories will not be included in the
     *                   search. Use TrueFileFilter.INSTANCE to match all directories.
     * @return an iterator of java.io.File for the matching files
     * @see org.apache.commons.io.filefilter.FileFilterUtils
     * @see org.apache.commons.io.filefilter.NameFileFilter
     * @since 2.2
     */
    public static Iterator<File> iterateFilesAndDirs(final File directory, final IOFileFilter fileFilter,
                                                     final IOFileFilter dirFilter) {
        return FileUtils.iterateFilesAndDirs(directory, fileFilter, dirFilter);
    }

    /**
     * 在给定的目录（和可选的子目录）中查找匹配一组扩展名的文件。
     *
     * @param directory  the directory to search in
     * @param extensions an array of extensions, ex. {"java","xml"}. If this
     *                   parameter is {@code null}, all files are returned.
     * @param recursive  if true all subdirectories are searched as well
     * @return an collection of java.io.File with the matching files
     */
    public static Collection<File> listFiles(
            final File directory, final String[] extensions, final boolean recursive) {
        return FileUtils.listFiles(directory, extensions, recursive);
    }

    /**
     * 允许迭代与扩展数组匹配的给定目录（及其子目录）中的文件。这个方法基于listFiles(File, String[], boolean)，支持Iterable（'foreach'循环）。
     *
     * @param directory  the directory to search in
     * @param extensions an array of extensions, ex. {"java","xml"}. If this
     *                   parameter is {@code null}, all files are returned.
     * @param recursive  if true all subdirectories are searched as well
     * @return an iterator of java.io.File with the matching files
     * @since 1.2
     */
    public static Iterator<File> iterateFiles(
            final File directory, final String[] extensions, final boolean recursive) {
        return FileUtils.iterateFiles(directory, extensions, recursive);
    }

    //-----------------------------------------------------------------------
    /**
     * 比较两个文件的内容以确定它们是否相等。
		这个方法检查两个文件是否是不同的长度，或者是否指向相同的文件，然后逐个比较内容。
     *
     * @param file1 the first file
     * @param file2 the second file
     * @return true if the content of the files are equal or they both don't
     * exist, false otherwise
     * @throws IOException in case of an I/O error
     */
    public static boolean contentEquals(final File file1, final File file2) throws IOException {
    	return FileUtils.contentEquals(file1, file2);
    }

    //-----------------------------------------------------------------------
    /**
     * 比较两个文件的内容以确定它们是否相等。
		这个方法检查两个文件是否指向相同的文件，然后逐行比较内容。
     *
     * @param file1       the first file
     * @param file2       the second file
     * @param charsetName the character encoding to be used.
     *                    May be null, in which case the platform default is used
     * @return true if the content of the files are equal or neither exists,
     * false otherwise
     * @throws IOException in case of an I/O error
     * @see IOUtils#contentEqualsIgnoreEOL(Reader, Reader)
     * @since 2.2
     */
    public static boolean contentEqualsIgnoreEOL(final File file1, final File file2, final String charsetName)
            throws IOException {
        return FileUtils.contentEqualsIgnoreEOL(file1, file2, charsetName);
    }

    //-----------------------------------------------------------------------
    /**
     * 从a转换URL为a File。
		从版本1.1这个方法将解码的URL。语法如file:///my%20docs/file.txt正确解码为/my docs/file.txt。从版本1.5开始，此方法使用UTF-8将百分比编码的八位字节解码为字符。此外，格式错误的百分比编码八位字节通过字面传递，从宽松处理。
     *
     * @param url the file URL to convert, {@code null} returns {@code null}
     * @return the equivalent <code>File</code> object, or {@code null}
     * if the URL's protocol is not <code>file</code>
     */
    public static File toFile(final URL url) {
        return FileUtils.toFile(url);
    }

    /**
     * 将每个数组转换URL为File。
		返回与输入相同大小的数组。如果输入是null，则返回一个空数组。如果输入包含null，则输出数组包含null相同的索引。

		该方法将解码URL。语法如file:///my%20docs/file.txt正确解码为/my docs/file.txt。
     *
     * @param urls the file URLs to convert, {@code null} returns empty array
     * @return a non-{@code null} array of Files matching the input, with a {@code null} item
     * if there was a {@code null} at that index in the input array
     * @throws IllegalArgumentException if any file is not a URL file
     * @throws IllegalArgumentException if any file is incorrectly encoded
     * @since 1.1
     */
    public static File[] toFiles(final URL[] urls) {
        return FileUtils.toFiles(urls);
    }

    /**
     * 将每个数组转换File为URL。
		返回与输入相同大小的数组。
     *
     * @param files the files to convert, must not be {@code null}
     * @return an array of URLs matching the input
     * @throws IOException          if a file cannot be converted
     * @throws NullPointerException if the parameter is null
     */
    public static URL[] toURLs(final File[] files) throws IOException {
        return FileUtils.toURLs(files);
    }

    //-----------------------------------------------------------------------
    /**
     * 将文件复制到保存文件日期的目录。
		此方法将指定的源文件的内容复制到指定的目标目录中具有相同名称的文件。如果目标目录不存在，则创建目标目录。如果目标文件存在，则此方法将覆盖它。
		注意：此方法尝试使用保留文件的上次修改日期/时间File.setLastModified(long)，但不保证该操作将成功。如果修改操作失败，则不提供任何指示。
     *
     * @param srcFile an existing file to copy, must not be {@code null}
     * @param destDir the directory to place the copy in, must not be {@code null}
     *
     * @throws NullPointerException if source or destination is null
     * @throws IOException          if source or destination is invalid
     * @throws IOException          if an IO error occurs during copying
     * @see #copyFile(File, File, boolean)
     */
    public static void copyFileToDirectory(final File srcFile, final File destDir) throws IOException {
    	FileUtils.copyFileToDirectory(srcFile, destDir);
    }

    /**
     * 将文件复制到可以保存文件日期的目录。
	此方法将指定的源文件的内容复制到指定的目标目录中具有相同名称的文件。如果目标目录不存在，则创建目标目录。如果目标文件存在，则此方法将覆盖它。

	注：设置preserveFileDate为 true尝试保留文件的最后修改日期/时间File.setLastModified(long)，但不能保证操作成功。如果修改操作失败，则不提供任何指示。
     *
     * @param srcFile          an existing file to copy, must not be {@code null}
     * @param destDir          the directory to place the copy in, must not be {@code null}
     * @param preserveFileDate true if the file date of the copy
     *                         should be the same as the original
     *
     * @throws NullPointerException if source or destination is {@code null}
     * @throws IOException          if source or destination is invalid
     * @throws IOException          if an IO error occurs during copying
     * @throws IOException          if the output file length is not the same as the input file length after the copy
     * completes
     * @see #copyFile(File, File, boolean)
     * @since 1.3
     */
    public static void copyFileToDirectory(final File srcFile, final File destDir, final boolean preserveFileDate)
            throws IOException {
    	FileUtils.copyFileToDirectory(srcFile, destDir, preserveFileDate);
    }

    /**
     * 将文件复制到保存文件日期的新位置。
		此方法将指定源文件的内容复制到指定的目标文件。保存目标文件的目录是不存在的。如果目标文件存在，则此方法将覆盖它。

		注意：此方法尝试使用保留文件的上次修改日期/时间File.setLastModified(long)，但不保证该操作将成功。如果修改操作失败，则不提供任何指示。
     *
     * @param srcFile  an existing file to copy, must not be {@code null}
     * @param destFile the new file, must not be {@code null}
     *
     * @throws NullPointerException if source or destination is {@code null}
     * @throws IOException          if source or destination is invalid
     * @throws IOException          if an IO error occurs during copying
     * @throws IOException          if the output file length is not the same as the input file length after the copy
     * completes
     * @see #copyFileToDirectory(File, File)
     * @see #copyFile(File, File, boolean)
     */
    public static void copyFile(final File srcFile, final File destFile) throws IOException {
    	FileUtils.copyFile(srcFile, destFile);
    }

    /**
     * 将文件复制到新位置。
此方法将指定源文件的内容复制到指定的目标文件。保存目标文件的目录是不存在的。如果目标文件存在，则此方法将覆盖它。

注：设置preserveFileDate为 true尝试保留文件的最后修改日期/时间File.setLastModified(long)，但不能保证操作成功。如果修改操作失败，则不提供任何指示。
     *
     * @param srcFile          an existing file to copy, must not be {@code null}
     * @param destFile         the new file, must not be {@code null}
     * @param preserveFileDate true if the file date of the copy
     *                         should be the same as the original
     *
     * @throws NullPointerException if source or destination is {@code null}
     * @throws IOException          if source or destination is invalid
     * @throws IOException          if an IO error occurs during copying
     * @throws IOException          if the output file length is not the same as the input file length after the copy
     * completes
     * @see #copyFileToDirectory(File, File, boolean)
     * @see #doCopyFile(File, File, boolean)
     */
    public static void copyFile(final File srcFile, final File destFile,
                                final boolean preserveFileDate) throws IOException {
    	FileUtils.copyFile(srcFile, destFile, preserveFileDate);
    }

    /**
     * 从a复制字节File到OutputStream。
		这个方法在内部缓冲输入，所以不需要使用a BufferedInputStream。
     *
     * @param input  the <code>File</code> to read from
     * @param output the <code>OutputStream</code> to write to
     * @return the number of bytes copied
     * @throws NullPointerException if the input or output is null
     * @throws IOException          if an I/O error occurs
     * @since 2.1
     */
    public static long copyFile(final File input, final OutputStream output) throws IOException {
    	return FileUtils.copyFile(input, output);
    }

    //-----------------------------------------------------------------------
    /**
     * 将目录复制到保存文件日期的另一个目录中。
此方法将源目录及其所有内容复制到指定的目标目录中具有相同名称的目录。

如果目标目录不存在，则创建目标目录。如果目标目录确实存在，则此方法将源与目标合并，源优先。

注意：此方法尝试使用文件的上次修改日期/时间File.setLastModified(long)，但不保证这些操作会成功。如果修改操作失败，则不提供任何指示。
     *
     * @param srcDir  an existing directory to copy, must not be {@code null}
     * @param destDir the directory to place the copy in, must not be {@code null}
     *
     * @throws NullPointerException if source or destination is {@code null}
     * @throws IOException          if source or destination is invalid
     * @throws IOException          if an IO error occurs during copying
     * @since 1.2
     */
    public static void copyDirectoryToDirectory(final File srcDir, final File destDir) throws IOException {
    	FileUtils.copyDirectoryToDirectory(srcDir, destDir);
    }

    /**
     * 将整个目录复制到保存文件日期的新位置。
此方法将指定的目录及其所有子目录和文件复制到指定的目标。目的地是目录的新位置和名称。

如果目标目录不存在，则创建目标目录。如果目标目录确实存在，则此方法将源与目标合并，源优先。

注意：此方法尝试使用文件的上次修改日期/时间File.setLastModified(long)，但不保证这些操作会成功。如果修改操作失败，则不提供任何指示。
     *
     * @param srcDir  an existing directory to copy, must not be {@code null}
     * @param destDir the new directory, must not be {@code null}
     *
     * @throws NullPointerException if source or destination is {@code null}
     * @throws IOException          if source or destination is invalid
     * @throws IOException          if an IO error occurs during copying
     * @since 1.1
     */
    public static void copyDirectory(final File srcDir, final File destDir) throws IOException {
    	FileUtils.copyDirectory(srcDir, destDir);
    }

    /**
     * 将整个目录复制到新位置。
此方法将指定源目录的内容复制到指定的目标目录中。

如果目标目录不存在，则创建目标目录。如果目标目录确实存在，则此方法将源与目标合并，源优先。

注意：设置preserveFileDate要 true尝试使用保存文件的最后修改日期/时间File.setLastModified(long)，但它不能保证这些行动会成功。如果修改操作失败，则不提供任何指示。
     *
     * @param srcDir           an existing directory to copy, must not be {@code null}
     * @param destDir          the new directory, must not be {@code null}
     * @param preserveFileDate true if the file date of the copy
     *                         should be the same as the original
     *
     * @throws NullPointerException if source or destination is {@code null}
     * @throws IOException          if source or destination is invalid
     * @throws IOException          if an IO error occurs during copying
     * @since 1.1
     */
    public static void copyDirectory(final File srcDir, final File destDir,
                                     final boolean preserveFileDate) throws IOException {
    	FileUtils.copyDirectory(srcDir, destDir, preserveFileDate);
    }

    /**
     *将已过滤的目录复制到保留文件日期的新位置。
此方法将指定源目录的内容复制到指定的目标目录中。

如果目标目录不存在，则创建目标目录。如果目标目录确实存在，则此方法将源与目标合并，源优先。

注意：此方法尝试使用文件的上次修改日期/时间File.setLastModified(long)，但不保证这些操作会成功。如果修改操作失败，则不提供任何指示。
     *
     * @param srcDir  an existing directory to copy, must not be {@code null}
     * @param destDir the new directory, must not be {@code null}
     * @param filter  the filter to apply, null means copy all directories and files
     *                should be the same as the original
     *
     * @throws NullPointerException if source or destination is {@code null}
     * @throws IOException          if source or destination is invalid
     * @throws IOException          if an IO error occurs during copying
     * @since 1.4
     */
    public static void copyDirectory(final File srcDir, final File destDir,
                                     final FileFilter filter) throws IOException {
    	FileUtils.copyDirectory(srcDir, destDir, filter);
    }

    /**
     * 将过滤的目录复制到新的位置。
此方法将指定源目录的内容复制到指定的目标目录中。

如果目标目录不存在，则创建目标目录。如果目标目录确实存在，则此方法将源与目标合并，源优先。

注意：设置preserveFileDate要 true尝试使用保存文件的最后修改日期/时间File.setLastModified(long)，但它不能保证这些行动会成功。如果修改操作失败，则不提供任何指示。
     *
     * @param srcDir           an existing directory to copy, must not be {@code null}
     * @param destDir          the new directory, must not be {@code null}
     * @param filter           the filter to apply, null means copy all directories and files
     * @param preserveFileDate true if the file date of the copy
     *                         should be the same as the original
     *
     * @throws NullPointerException if source or destination is {@code null}
     * @throws IOException          if source or destination is invalid
     * @throws IOException          if an IO error occurs during copying
     * @since 1.4
     */
    public static void copyDirectory(final File srcDir, final File destDir,
                                     final FileFilter filter, final boolean preserveFileDate) throws IOException {
    	FileUtils.copyDirectory(srcDir, destDir, preserveFileDate);
    }

    //-----------------------------------------------------------------------
    /**
     * 将URL source中的字节复制到文件中 destination。destination 如果它们不存在，将会创建最多的目录。destination 将被覆盖，如果它已经存在。
警告：此方法不会设置连接或读取超时，因此可能永远阻塞。使用copyURLToFile(URL, File, int, int) 合理的超时来防止这种情况。
     *
     * @param source      the <code>URL</code> to copy bytes from, must not be {@code null}
     * @param destination the non-directory <code>File</code> to write bytes to
     *                    (possibly overwriting), must not be {@code null}
     * @throws IOException if <code>source</code> URL cannot be opened
     * @throws IOException if <code>destination</code> is a directory
     * @throws IOException if <code>destination</code> cannot be written
     * @throws IOException if <code>destination</code> needs creating but can't be
     * @throws IOException if an IO error occurs during copying
     */
    public static void copyURLToFile(final URL source, final File destination) throws IOException {
    	FileUtils.copyURLToFile(source, destination);
    }

    /**
     * 将URL source中的字节复制到文件中 destination。destination 如果它们不存在，将会创建最多的目录。destination 将被覆盖，如果它已经存在。
     *
     * @param source            the <code>URL</code> to copy bytes from, must not be {@code null}
     * @param destination       the non-directory <code>File</code> to write bytes to
     *                          (possibly overwriting), must not be {@code null}
     * @param connectionTimeout the number of milliseconds until this method
     *                          will timeout if no connection could be established to the <code>source</code>
     * @param readTimeout       the number of milliseconds until this method will
     *                          timeout if no data could be read from the <code>source</code>
     * @throws IOException if <code>source</code> URL cannot be opened
     * @throws IOException if <code>destination</code> is a directory
     * @throws IOException if <code>destination</code> cannot be written
     * @throws IOException if <code>destination</code> needs creating but can't be
     * @throws IOException if an IO error occurs during copying
     * @since 2.0
     */
    public static void copyURLToFile(final URL source, final File destination,
                                     final int connectionTimeout, final int readTimeout) throws IOException {
    	FileUtils.copyURLToFile(source, destination);
    }

    /**
     * 将字节从一个文件复制到一个文件 。 如果它们不存在，将会创建最多的目录。 将被覆盖，如果它已经存在。该流已关闭。请参阅不关闭输入流的方法
     *
     * @param source      the <code>InputStream</code> to copy bytes from, must not be {@code null}, will be closed
     * @param destination the non-directory <code>File</code> to write bytes to
     *                    (possibly overwriting), must not be {@code null}
     * @throws IOException if <code>destination</code> is a directory
     * @throws IOException if <code>destination</code> cannot be written
     * @throws IOException if <code>destination</code> needs creating but can't be
     * @throws IOException if an IO error occurs during copying
     * @since 2.0
     */
    public static void copyInputStreamToFile(final InputStream source, final File destination) throws IOException {
    	FileUtils.copyInputStreamToFile(source, destination);
    }

    /**
     * 将字节从一个文件复制到一个文件 。 如果它们不存在，将会创建最多的目录。 将被覆盖，如果它已经存在。这个小河保持开放，例如与...一起使用。请参阅关闭输入流的方法
     *
     * @param source      the <code>InputStream</code> to copy bytes from, must not be {@code null}
     * @param destination the non-directory <code>File</code> to write bytes to
     *                    (possibly overwriting), must not be {@code null}
     * @throws IOException if <code>destination</code> is a directory
     * @throws IOException if <code>destination</code> cannot be written
     * @throws IOException if <code>destination</code> needs creating but can't be
     * @throws IOException if an IO error occurs during copying
     * @since 2.5
     */
    public static void copyToFile(final InputStream source, final File destination) throws IOException {
    	FileUtils.copyToFile(source, destination);
    }

    //-----------------------------------------------------------------------
    /**
     * 递归删除一个目录。
     *
     * @param directory directory to delete
     * @throws IOException              in case deletion is unsuccessful
     * @throws IllegalArgumentException if {@code directory} does not exist or is not a directory
     */
    public static void deleteDirectory(final File directory) throws IOException {
    	FileUtils.deleteDirectory(directory);
    }

    /**
     * 删除一个文件，永远不会抛出一个异常。如果文件是一个目录，删除它和所有的子目录。
     * File.delete（）和这个方法的区别是：
要删除的目录不一定是空的。
无法删除文件或目录时，不会引发异常。
     *
     * @param file file or directory to delete, can be {@code null}
     * @return {@code true} if the file or directory was deleted, otherwise
     * {@code false}
     *
     * @since 1.4
     */
    public static boolean deleteQuietly(final File file) {
    	return FileUtils.deleteQuietly(file);
    }

    /**
     *确定parent目录是否包含child元素（文件或目录）。
文件在比较之前被归一化。

边缘情况：
一个directory不能为null：如果为null，抛出IllegalArgumentException
A directory必须是一个目录：如果不是目录，则抛出IllegalArgumentException
目录不包含自身：return false
空的子文件不包含在任何父项中：return false
     *
     * @param directory the file to consider as the parent.
     * @param child     the file to consider as the child.
     * @return true is the candidate leaf is under by the specified composite. False otherwise.
     * @throws IOException              if an IO error occurs while checking the files.
     * @throws IllegalArgumentException if {@code directory} is null or not a directory.
     * @see FilenameUtils#directoryContains(String, String)
     * @since 2.2
     */
    public static boolean directoryContains(final File directory, final File child) throws IOException {
    	return FileUtils.directoryContains(directory, child);
    }

    /**
     * 清除目录而不删除它。
     *
     * @param directory directory to clean
     * @throws IOException              in case cleaning is unsuccessful
     * @throws IllegalArgumentException if {@code directory} does not exist or is not a directory
     */
    public static void cleanDirectory(final File directory) throws IOException {
    	FileUtils.cleanDirectory(directory);
    }

    //-----------------------------------------------------------------------
    /**
     * 等待NFS传播文件创建，强制超时。
此方法重复测试，File.exists()直到它返回true，直到以秒为单位指定的最长时间。
     *
     * @param file    the file to check, must not be {@code null}
     * @param seconds the maximum time in seconds to wait
     * @return true if file exists
     * @throws NullPointerException if the file is {@code null}
     */
    public static boolean waitFor(final File file, final int seconds) {
        return FileUtils.waitFor(file, seconds);
    }

    //-----------------------------------------------------------------------
    /**
     * 将文件的内容读入字符串。该文件始终关闭。
     *
     * @param file     the file to read, must not be {@code null}
     * @param encoding the encoding to use, {@code null} means platform default
     * @return the file contents, never {@code null}
     * @throws IOException in case of an I/O error
     * @since 2.3
     */
    public static String readFileToString(final File file, final Charset encoding) throws IOException {
        return FileUtils.readFileToString(file, encoding);
    }

    /**
     * 将文件的内容读入字符串。该文件始终关闭。
     *
     * @param file     the file to read, must not be {@code null}
     * @param encoding the encoding to use, {@code null} means platform default
     * @return the file contents, never {@code null}
     * @throws IOException                 in case of an I/O error
     * @throws java.nio.charset.UnsupportedCharsetException thrown instead of {@link java.io
     * .UnsupportedEncodingException} in version 2.2 if the encoding is not supported.
     * @since 2.3
     */
    public static String readFileToString(final File file, final String encoding) throws IOException {
        return FileUtils.readFileToString(file, encoding);
    }


    /**
     * 使用VM的默认编码将文件的内容读入字符串。该文件始终关闭。
     *
     * @param file the file to read, must not be {@code null}
     * @return the file contents, never {@code null}
     * @throws IOException in case of an I/O error
     * @since 1.3.1
     * @deprecated 2.5 use {@link #readFileToString(File, Charset)} instead
     */
    @Deprecated
    public static String readFileToString(final File file) throws IOException {
        return FileUtils.readFileToString(file);
    }

    /**
     * 将文件的内容读入一个字节数组。该文件始终关闭。
     *
     * @param file the file to read, must not be {@code null}
     * @return the file contents, never {@code null}
     * @throws IOException in case of an I/O error
     * @since 1.1
     */
    public static byte[] readFileToByteArray(final File file) throws IOException {
    	return FileUtils.readFileToByteArray(file);
    }

    /**
     * 逐行读取文件的内容到字符串列表。该文件始终关闭。
     *
     * @param file     the file to read, must not be {@code null}
     * @param encoding the encoding to use, {@code null} means platform default
     * @return the list of Strings representing each line in the file, never {@code null}
     * @throws IOException in case of an I/O error
     * @since 2.3
     */
    public static List<String> readLines(final File file, final Charset encoding) throws IOException {
        return FileUtils.readLines(file, encoding);
    }

    /**
     * 逐行读取文件的内容到字符串列表。该文件始终关闭。
     *
     * @param file     the file to read, must not be {@code null}
     * @param encoding the encoding to use, {@code null} means platform default
     * @return the list of Strings representing each line in the file, never {@code null}
     * @throws IOException                 in case of an I/O error
     * @throws java.nio.charset.UnsupportedCharsetException thrown instead of {@link java.io
     * .UnsupportedEncodingException} in version 2.2 if the encoding is not supported.
     * @since 1.1
     */
    public static List<String> readLines(final File file, final String encoding) throws IOException {
        return FileUtils.readLines(file, encoding);
    }

    /**
     * 使用VM的默认编码，逐行读取文件的内容到字符串列表。该文件始终关闭。
     *
     * @param file the file to read, must not be {@code null}
     * @return the list of Strings representing each line in the file, never {@code null}
     * @throws IOException in case of an I/O error
     * @since 1.3
     * @deprecated 2.5 use {@link #readLines(File, Charset)} instead
     */
    @Deprecated
    public static List<String> readLines(final File file) throws IOException {
    	return FileUtils.readLines(file);
    }

    /**
     * 返回a中的行的迭代器File。
这个方法打开一个InputStream文件。当您完成迭代器时，您应关闭流以释放内部资源。这可以通过调用LineIterator.close()or LineIterator.closeQuietly(LineIterator)方法来完成 。

推荐的使用模式是：

 LineIterator it = FileUtils.lineIterator（file，“UTF-8”）;
 尝试{
   while（it.hasNext（））{
     String line = it.nextLine（）;
     ///用线做点什么
   }
 最后{
   LineIterator.closeQuietly（迭代）;
 }
 
如果在创建迭代器的过程中发生异常，则关闭基础流。
     *
     * @param file     the file to open for input, must not be {@code null}
     * @param encoding the encoding to use, {@code null} means platform default
     * @return an Iterator of the lines in the file, never {@code null}
     * @throws IOException in case of an I/O error (file closed)
     * @since 1.2
     */
    public static LineIterator lineIterator(final File file, final String encoding) throws IOException {
    	return FileUtils.lineIterator(file, encoding);
    }

    /**
     * File使用默认编码为VM 返回行的迭代器。
     *
     * @param file the file to open for input, must not be {@code null}
     * @return an Iterator of the lines in the file, never {@code null}
     * @throws IOException in case of an I/O error (file closed)
     * @see #lineIterator(File, String)
     * @since 1.3
     */
    public static LineIterator lineIterator(final File file) throws IOException {
        return FileUtils.lineIterator(file);
    }

    //-----------------------------------------------------------------------

    /**
     * 将字符串写入创建该文件的文件（如果该文件不存在）。
注意：从v1.3开始，文件的父目录将被创建（如果它们不存在）。
     *
     * @param file     the file to write
     * @param data     the content to write to the file
     * @param encoding the encoding to use, {@code null} means platform default
     * @throws IOException                          in case of an I/O error
     * @throws java.io.UnsupportedEncodingException if the encoding is not supported by the VM
     * @since 2.4
     */
    public static void writeStringToFile(final File file, final String data, final Charset encoding)
            throws IOException {
    	FileUtils.write(file, data, encoding);
    }

    /**
     * 将字符串写入创建该文件的文件（如果该文件不存在）。
注意：从v1.3开始，文件的父目录将被创建（如果它们不存在）。
     *
     * @param file     the file to write
     * @param data     the content to write to the file
     * @param encoding the encoding to use, {@code null} means platform default
     * @throws IOException                          in case of an I/O error
     * @throws java.io.UnsupportedEncodingException if the encoding is not supported by the VM
     */
    public static void writeStringToFile(final File file, final String data, final String encoding) throws IOException {
    	FileUtils.writeStringToFile(file, data, encoding);
    }

    /**
     * 将字符串写入创建该文件的文件（如果该文件不存在）。
     *
     * @param file     the file to write
     * @param data     the content to write to the file
     * @param encoding the encoding to use, {@code null} means platform default
     * @param append   if {@code true}, then the String will be added to the
     *                 end of the file rather than overwriting
     * @throws IOException in case of an I/O error
     * @since 2.3
     */
    public static void writeStringToFile(final File file, final String data, final Charset encoding, final boolean
            append) throws IOException {
    	FileUtils.writeStringToFile(file, data, encoding, append);
    }

    /**
     * 将字符串写入创建该文件的文件（如果该文件不存在）。
     *
     * @param file     the file to write
     * @param data     the content to write to the file
     * @param encoding the encoding to use, {@code null} means platform default
     * @param append   if {@code true}, then the String will be added to the
     *                 end of the file rather than overwriting
     * @throws IOException                 in case of an I/O error
     * @throws java.nio.charset.UnsupportedCharsetException thrown instead of {@link java.io
     * .UnsupportedEncodingException} in version 2.2 if the encoding is not supported by the VM
     * @since 2.1
     */
    public static void writeStringToFile(final File file, final String data, final String encoding,
                                         final boolean append) throws IOException {
    	FileUtils.writeStringToFile(file, data, encoding, append);
    }

    /**
     * 如果文件不存在，则使用VM的默认编码将字符串写入创建文件的文件中。
     *
     * @param file the file to write
     * @param data the content to write to the file
     * @throws IOException in case of an I/O error
     * @deprecated 2.5 use {@link #writeStringToFile(File, String, Charset)} instead
     */
    @Deprecated
    public static void writeStringToFile(final File file, final String data) throws IOException {
    	FileUtils.writeStringToFile(file, data);
    }

    /**
     * 如果文件不存在，则使用VM的默认编码将字符串写入创建文件的文件中。
     *
     * @param file   the file to write
     * @param data   the content to write to the file
     * @param append if {@code true}, then the String will be added to the
     *               end of the file rather than overwriting
     * @throws IOException in case of an I/O error
     * @since 2.1
     * @deprecated 2.5 use {@link #writeStringToFile(File, String, Charset, boolean)} instead
     */
    @Deprecated
    public static void writeStringToFile(final File file, final String data, final boolean append) throws IOException {
    	FileUtils.writeStringToFile(file, data, append);
    }

    /**
     * 将CharSequence写入创建文件的文件（如果该文件不存在，则使用VM的默认编码）。
     *
     * @param file the file to write
     * @param data the content to write to the file
     * @throws IOException in case of an I/O error
     * @since 2.0
     * @deprecated 2.5 use {@link #write(File, CharSequence, Charset)} instead
     */
    @Deprecated
    public static void write(final File file, final CharSequence data) throws IOException {
    	FileUtils.write(file, data);
    }

    /**
     * 将CharSequence写入创建文件的文件（如果该文件不存在，则使用VM的默认编码）
     *
     * @param file   the file to write
     * @param data   the content to write to the file
     * @param append if {@code true}, then the data will be added to the
     *               end of the file rather than overwriting
     * @throws IOException in case of an I/O error
     * @since 2.1
     * @deprecated 2.5 use {@link #write(File, CharSequence, Charset, boolean)} instead
     */
    @Deprecated
    public static void write(final File file, final CharSequence data, final boolean append) throws IOException {
    	FileUtils.write(file, data, append);
    }

    /**
     * 将CharSequence写入创建该文件的文件（如果该文件不存在）。
     *
     * @param file     the file to write
     * @param data     the content to write to the file
     * @param encoding the encoding to use, {@code null} means platform default
     * @throws IOException in case of an I/O error
     * @since 2.3
     */
    public static void write(final File file, final CharSequence data, final Charset encoding) throws IOException {
    	FileUtils.write(file, data, encoding);
    }

    /**
     * 将CharSequence写入创建该文件的文件（如果该文件不存在）。
     *
     * @param file     the file to write
     * @param data     the content to write to the file
     * @param encoding the encoding to use, {@code null} means platform default
     * @throws IOException                          in case of an I/O error
     * @throws java.io.UnsupportedEncodingException if the encoding is not supported by the VM
     * @since 2.0
     */
    public static void write(final File file, final CharSequence data, final String encoding) throws IOException {
    	FileUtils.write(file, data, encoding);
    }

    /**
     * 将CharSequence写入创建该文件的文件（如果该文件不存在）。
     *
     * @param file     the file to write
     * @param data     the content to write to the file
     * @param encoding the encoding to use, {@code null} means platform default
     * @param append   if {@code true}, then the data will be added to the
     *                 end of the file rather than overwriting
     * @throws IOException in case of an I/O error
     * @since 2.3
     */
    public static void write(final File file, final CharSequence data, final Charset encoding, final boolean append)
            throws IOException {
    	FileUtils.write(file, data, encoding, append);
    }

    /**
     * 将CharSequence写入创建该文件的文件（如果该文件不存在）。
     *
     * @param file     the file to write
     * @param data     the content to write to the file
     * @param encoding the encoding to use, {@code null} means platform default
     * @param append   if {@code true}, then the data will be added to the
     *                 end of the file rather than overwriting
     * @throws IOException                 in case of an I/O error
     * @throws java.nio.charset.UnsupportedCharsetException thrown instead of {@link java.io
     * .UnsupportedEncodingException} in version 2.2 if the encoding is not supported by the VM
     * @since 2.1
     */
    public static void write(final File file, final CharSequence data, final String encoding, final boolean append)
            throws IOException {
    	FileUtils.write(file, data, encoding, append);
    }

    /**
     * 将一个字节数组写入创建该文件的文件（如果该文件不存在）。
注意：从v1.3开始，文件的父目录将被创建（如果它们不存在）。
     *
     * @param file the file to write to
     * @param data the content to write to the file
     * @throws IOException in case of an I/O error
     * @since 1.1
     */
    public static void writeByteArrayToFile(final File file, final byte[] data) throws IOException {
    	FileUtils.writeByteArrayToFile(file, data);
    }

    /**
     *  将一个字节数组写入创建该文件的文件（如果该文件不存在）。
     *
     * @param file   the file to write to
     * @param data   the content to write to the file
     * @param append if {@code true}, then bytes will be added to the
     *               end of the file rather than overwriting
     * @throws IOException in case of an I/O error
     * @since 2.1
     */
    public static void writeByteArrayToFile(final File file, final byte[] data, final boolean append)
            throws IOException {
    	FileUtils.writeByteArrayToFile(file, data, append);
    }

    /**
     *将len指定的字节数组中的字节从offset开始写入off文件，如果文件不存在则创建文件。
     *
     * @param file the file to write to
     * @param data the content to write to the file
     * @param off  the start offset in the data
     * @param len  the number of bytes to write
     * @throws IOException in case of an I/O error
     * @since 2.5
     */
    public static void writeByteArrayToFile(final File file, final byte[] data, final int off, final int len)
            throws IOException {
    	FileUtils.writeByteArrayToFile(file, data, off, len);
    }

    /**
     * 将len指定的字节数组中的字节从offset开始写入off文件，如果文件不存在则创建文件。
     *
     * @param file   the file to write to
     * @param data   the content to write to the file
     * @param off    the start offset in the data
     * @param len    the number of bytes to write
     * @param append if {@code true}, then bytes will be added to the
     *               end of the file rather than overwriting
     * @throws IOException in case of an I/O error
     * @since 2.5
     */
    public static void writeByteArrayToFile(final File file, final byte[] data, final int off, final int len,
                                            final boolean append) throws IOException {
    	FileUtils.writeByteArrayToFile(file, data, off, len, append);
    }

    /**
     * 将toString()集合中的每个项目的值写入指定File的行。将使用指定的字符编码和默认行结束符。
注意：从v1.3开始，文件的父目录将被创建（如果它们不存在）。
     *
     * @param file     the file to write to
     * @param encoding the encoding to use, {@code null} means platform default
     * @param lines    the lines to write, {@code null} entries produce blank lines
     * @throws IOException                          in case of an I/O error
     * @throws java.io.UnsupportedEncodingException if the encoding is not supported by the VM
     * @since 1.1
     */
    public static void writeLines(final File file, final String encoding, final Collection<?> lines)
            throws IOException {
    	FileUtils.writeLines(file, encoding, lines);
    }

    /**
     * 将toString()集合中的每个项目的值写入指定File的行，可以选择追加。将使用指定的字符编码和默认行结束符。
     *
     * @param file     the file to write to
     * @param encoding the encoding to use, {@code null} means platform default
     * @param lines    the lines to write, {@code null} entries produce blank lines
     * @param append   if {@code true}, then the lines will be added to the
     *                 end of the file rather than overwriting
     * @throws IOException                          in case of an I/O error
     * @throws java.io.UnsupportedEncodingException if the encoding is not supported by the VM
     * @since 2.1
     */
    public static void writeLines(final File file, final String encoding, final Collection<?> lines,
                                  final boolean append) throws IOException {
    	FileUtils.writeLines(file, lines, append);
    }

    /**
     * 将toString()集合中的每个项目的值写入指定File的行。将使用默认的VM编码和默认行结束。
     *
     * @param file  the file to write to
     * @param lines the lines to write, {@code null} entries produce blank lines
     * @throws IOException in case of an I/O error
     * @since 1.3
     */
    public static void writeLines(final File file, final Collection<?> lines) throws IOException {
    	FileUtils.writeLines(file, lines);
    }

    /**
     * 将toString()集合中的每个项目的值写入指定File的行。将使用默认的VM编码和默认行结束。
     *
     * @param file   the file to write to
     * @param lines  the lines to write, {@code null} entries produce blank lines
     * @param append if {@code true}, then the lines will be added to the
     *               end of the file rather than overwriting
     * @throws IOException in case of an I/O error
     * @since 2.1
     */
    public static void writeLines(final File file, final Collection<?> lines, final boolean append) throws IOException {
    	FileUtils.writeLines(file, lines, append);
    }

    /**
     * 将toString()集合中的每个项目的值写入指定File的行。指定的字符编码和行结束将被使用。
注意：从v1.3开始，文件的父目录将被创建（如果它们不存在）。
     *
     * @param file       the file to write to
     * @param encoding   the encoding to use, {@code null} means platform default
     * @param lines      the lines to write, {@code null} entries produce blank lines
     * @param lineEnding the line separator to use, {@code null} is system default
     * @throws IOException                          in case of an I/O error
     * @throws java.io.UnsupportedEncodingException if the encoding is not supported by the VM
     * @since 1.1
     */
    public static void writeLines(final File file, final String encoding, final Collection<?> lines,
                                  final String lineEnding) throws IOException {
    	FileUtils.writeLines(file, lines, lineEnding);
    }

    /**
     * 将toString()集合中的每个项目的值写入指定File的行。指定的字符编码和行结束将被使用。
     *
     * @param file       the file to write to
     * @param encoding   the encoding to use, {@code null} means platform default
     * @param lines      the lines to write, {@code null} entries produce blank lines
     * @param lineEnding the line separator to use, {@code null} is system default
     * @param append     if {@code true}, then the lines will be added to the
     *                   end of the file rather than overwriting
     * @throws IOException                          in case of an I/O error
     * @throws java.io.UnsupportedEncodingException if the encoding is not supported by the VM
     * @since 2.1
     */
    public static void writeLines(final File file, final String encoding, final Collection<?> lines,
                                  final String lineEnding, final boolean append) throws IOException {
    	FileUtils.writeLines(file, lines, append);
    }

    /**
     * 将toString()集合中的每个项目的值写入指定File的行。将使用默认的VM编码和指定的行尾。
     *
     * @param file       the file to write to
     * @param lines      the lines to write, {@code null} entries produce blank lines
     * @param lineEnding the line separator to use, {@code null} is system default
     * @throws IOException in case of an I/O error
     * @since 1.3
     */
    public static void writeLines(final File file, final Collection<?> lines, final String lineEnding)
            throws IOException {
    	FileUtils.writeLines(file, lines, lineEnding);
    }

    /**
     * 将toString()集合中的每个项目的值写入指定File的行。将使用默认的VM编码和指定的行尾。
     *
     * @param file       the file to write to
     * @param lines      the lines to write, {@code null} entries produce blank lines
     * @param lineEnding the line separator to use, {@code null} is system default
     * @param append     if {@code true}, then the lines will be added to the
     *                   end of the file rather than overwriting
     * @throws IOException in case of an I/O error
     * @since 2.1
     */
    public static void writeLines(final File file, final Collection<?> lines, final String lineEnding,
                                  final boolean append) throws IOException {
    	FileUtils.writeLines(file, lines, append);
    }

    //-----------------------------------------------------------------------
    /**
     * 删除一个文件。如果文件是一个目录，删除它和所有的子目录。
File.delete（）和这个方法的区别是：

要删除的目录不一定是空的。
当一个文件或目录不能被删除，你会得到例外。（java.io.File方法返回一个布尔值）
     *
     * @param file file or directory to delete, must not be {@code null}
     * @throws NullPointerException  if the directory is {@code null}
     * @throws FileNotFoundException if the file was not found
     * @throws IOException           in case deletion is unsuccessful
     */
    public static void forceDelete(final File file) throws IOException {
    	FileUtils.forceDelete(file);
    }

    /**
     * 计划在JVM退出时要删除的文件。如果文件是目录，删除它和所有的子目录。
     *
     * @param file file or directory to delete, must not be {@code null}
     * @throws NullPointerException if the file is {@code null}
     * @throws IOException          in case deletion is unsuccessful
     */
    public static void forceDeleteOnExit(final File file) throws IOException {
    	FileUtils.forceDeleteOnExit(file);
    }
    
    /**
     * 创建一个目录，包括任何必要但不存在的父目录。如果一个文件已经存在指定名称，但不是一个目录，则抛出一个IOException。如果目录不能被创建（或者不存在），则抛出IOException。
     *
     * @param directory directory to create, must not be {@code null}
     * @throws NullPointerException if the directory is {@code null}
     * @throws IOException          if the directory cannot be created or the file already exists but is not a directory
     */
    public static void forceMkdir(final File directory) throws IOException {
    	FileUtils.forceMkdir(directory);
    }

    /**
     * 为给定的文件创建任何必要但不存在的父目录。如果不能创建父目录，则抛出IOException。
     *
     * @param file file with parent to create, must not be {@code null}
     * @throws NullPointerException if the file is {@code null}
     * @throws IOException          if the parent directory cannot be created
     * @since 2.5
     */
    public static void forceMkdirParent(final File file) throws IOException {
    	FileUtils.forceMkdirParent(file);
    }

    //-----------------------------------------------------------------------
    /**
     * 返回指定文件或目录的大小。如果提供的 File是常规文件，则返回文件的长度。如果参数是一个目录，那么目录的大小是递归计算的。如果某个目录或子目录受到安全限制，则其大小将不会包含在内。
请注意，没有检测到溢出，如果发生溢出，则返回值可能为负值。请参阅sizeOfAsBigInteger(File)另一种不溢出的方法。
     *
     * @param file the regular file or directory to return the size
     *             of (must not be {@code null}).
     *
     * @return the length of the file, or recursive size of the directory,
     * provided (in bytes).
     *
     * @throws NullPointerException     if the file is {@code null}
     * @throws IllegalArgumentException if the file does not exist.
     *
     * @since 2.0
     */
    public static long sizeOf(final File file) {

    	return FileUtils.sizeOf(file);

    }

    /**
     * 返回指定文件或目录的大小。如果提供的 File是常规文件，则返回文件的长度。如果参数是一个目录，那么目录的大小是递归计算的。如果某个目录或子目录受到安全限制，则其大小将不会包含在内。
     *
     * @param file the regular file or directory to return the size
     *             of (must not be {@code null}).
     *
     * @return the length of the file, or recursive size of the directory,
     * provided (in bytes).
     *
     * @throws NullPointerException     if the file is {@code null}
     * @throws IllegalArgumentException if the file does not exist.
     *
     * @since 2.4
     */
    public static BigInteger sizeOfAsBigInteger(final File file) {

        return FileUtils.sizeOfAsBigInteger(file);

    }

    /**
     * 统计一个目录的大小递归（所有文件长度的总和）。
请注意，没有检测到溢出，如果发生溢出，则返回值可能为负值。请参阅sizeOfDirectoryAsBigInteger(File)另一种不溢出的方法。
     *
     * @param directory directory to inspect, must not be {@code null}
     * @return size of directory in bytes, 0 if directory is security restricted, a negative number when the real total
     * is greater than {@link Long#MAX_VALUE}.
     * @throws NullPointerException if the directory is {@code null}
     */
    public static long sizeOfDirectory(final File directory) {
        return FileUtils.sizeOfDirectory(directory);
    }

    // Private method, must be invoked will a directory parameter

    /**
     * 统计一个目录的大小递归（所有文件长度的总和）。
     *
     * @param directory directory to inspect, must not be {@code null}
     * @return size of directory in bytes, 0 if directory is security restricted.
     * @throws NullPointerException if the directory is {@code null}
     * @since 2.4
     */
    public static BigInteger sizeOfDirectoryAsBigInteger(final File directory) {
        return FileUtils.sizeOfDirectoryAsBigInteger(directory);
    }

    //-----------------------------------------------------------------------
    /**
     * 测试指定的File是否比参考更新 File。
     *
     * @param file      the <code>File</code> of which the modification date must
     *                  be compared, must not be {@code null}
     * @param reference the <code>File</code> of which the modification date
     *                  is used, must not be {@code null}
     * @return true if the <code>File</code> exists and has been modified more
     * recently than the reference <code>File</code>
     * @throws IllegalArgumentException if the file is {@code null}
     * @throws IllegalArgumentException if the reference file is {@code null} or doesn't exist
     */
    public static boolean isFileNewer(final File file, final File reference) {
        return FileUtils.isFileNewer(file, reference);
    }

    /**
     * 测试指定的File是否比指定的更新 Date。
     *
     * @param file the <code>File</code> of which the modification date
     *             must be compared, must not be {@code null}
     * @param date the date reference, must not be {@code null}
     * @return true if the <code>File</code> exists and has been modified
     * after the given <code>Date</code>.
     * @throws IllegalArgumentException if the file is {@code null}
     * @throws IllegalArgumentException if the date is {@code null}
     */
    public static boolean isFileNewer(final File file, final Date date) {
        return FileUtils.isFileNewer(file, date);
    }

    /**
     * 测试指定的File是否比指定的时间参考更新。
     *
     * @param file       the <code>File</code> of which the modification date must
     *                   be compared, must not be {@code null}
     * @param timeMillis the time reference measured in milliseconds since the
     *                   epoch (00:00:00 GMT, January 1, 1970)
     * @return true if the <code>File</code> exists and has been modified after
     * the given time reference.
     * @throws IllegalArgumentException if the file is {@code null}
     */
    public static boolean isFileNewer(final File file, final long timeMillis) {
        return FileUtils.isFileNewer(file, timeMillis);
    }


    //-----------------------------------------------------------------------
    /**
     * 测试指定的File是否比参考旧 File。
     *
     * @param file      the <code>File</code> of which the modification date must
     *                  be compared, must not be {@code null}
     * @param reference the <code>File</code> of which the modification date
     *                  is used, must not be {@code null}
     * @return true if the <code>File</code> exists and has been modified before
     * the reference <code>File</code>
     * @throws IllegalArgumentException if the file is {@code null}
     * @throws IllegalArgumentException if the reference file is {@code null} or doesn't exist
     */
    public static boolean isFileOlder(final File file, final File reference) {
        return FileUtils.isFileOlder(file, reference);
    }

    /**
     * 测试指定的File是否比指定的更早 Date。
     *
     * @param file the <code>File</code> of which the modification date
     *             must be compared, must not be {@code null}
     * @param date the date reference, must not be {@code null}
     * @return true if the <code>File</code> exists and has been modified
     * before the given <code>Date</code>.
     * @throws IllegalArgumentException if the file is {@code null}
     * @throws IllegalArgumentException if the date is {@code null}
     */
    public static boolean isFileOlder(final File file, final Date date) {
        return FileUtils.isFileOlder(file, date);
    }

    /**
     * 测试File指定的时间是否早于指定的时间参考。
     *
     * @param file       the <code>File</code> of which the modification date must
     *                   be compared, must not be {@code null}
     * @param timeMillis the time reference measured in milliseconds since the
     *                   epoch (00:00:00 GMT, January 1, 1970)
     * @return true if the <code>File</code> exists and has been modified before
     * the given time reference.
     * @throws IllegalArgumentException if the file is {@code null}
     */
    public static boolean isFileOlder(final File file, final long timeMillis) {
        return FileUtils.isFileOlder(file, timeMillis);
    }

    //-----------------------------------------------------------------------
    /**
     * 使用CRC32校验和例程计算文件的校验和。校验和的值被返回。
     *
     * @param file the file to checksum, must not be {@code null}
     * @return the checksum value
     * @throws NullPointerException     if the file or checksum is {@code null}
     * @throws IllegalArgumentException if the file is a directory
     * @throws IOException              if an IO error occurs reading the file
     * @since 1.3
     */
    public static long checksumCRC32(final File file) throws IOException {
        return FileUtils.checksumCRC32(file);
    }

    /**
     * 使用指定的校验和对象计算文件的校验和。Checksum如果需要，可以使用一个实例检查多个文件，只需重复使用相同的校验和对象即可。例如：
     * long csum = FileUtils.checksum（file，new CRC32（））。getValue（）;
     *
     * @param file     the file to checksum, must not be {@code null}
     * @param checksum the checksum object to be used, must not be {@code null}
     * @return the checksum specified, updated with the content of the file
     * @throws NullPointerException     if the file or checksum is {@code null}
     * @throws IllegalArgumentException if the file is a directory
     * @throws IOException              if an IO error occurs reading the file
     * @since 1.3
     */
    public static Checksum checksum(final File file, final Checksum checksum) throws IOException {
        return FileUtils.checksum(file, checksum);
    }

    /**
     * 移动目录。
当目标目录位于另一个文件系统上时，请执行“复制并删除”。
     *
     * @param srcDir  the directory to be moved
     * @param destDir the destination directory
     * @throws NullPointerException if source or destination is {@code null}
     * @throws FileExistsException  if the destination directory exists
     * @throws IOException          if source or destination is invalid
     * @throws IOException          if an IO error occurs moving the file
     * @since 1.4
     */
    public static void moveDirectory(final File srcDir, final File destDir) throws IOException {
    	FileUtils.moveDirectory(srcDir, destDir);
    }

    /**
     * 将目录移动到另一个目录。
     *
     * @param src           the file to be moved
     * @param destDir       the destination file
     * @param createDestDir If {@code true} create the destination directory,
     *                      otherwise if {@code false} throw an IOException
     * @throws NullPointerException if source or destination is {@code null}
     * @throws FileExistsException  if the directory exists in the destination directory
     * @throws IOException          if source or destination is invalid
     * @throws IOException          if an IO error occurs moving the file
     * @since 1.4
     */
    public static void moveDirectoryToDirectory(final File src, final File destDir, final boolean createDestDir)
            throws IOException {
    	FileUtils.moveDirectoryToDirectory(src, destDir, createDestDir);

    }

    /**
     * 移动一个文件。
当目标文件在另一个文件系统上时，请执行“复制并删除”。
     *
     * @param srcFile  the file to be moved
     * @param destFile the destination file
     * @throws NullPointerException if source or destination is {@code null}
     * @throws FileExistsException  if the destination file exists
     * @throws IOException          if source or destination is invalid
     * @throws IOException          if an IO error occurs moving the file
     * @since 1.4
     */
    public static void moveFile(final File srcFile, final File destFile) throws IOException {
    	FileUtils.moveFile(srcFile, destFile);
    }

    /**
     * 将文件移动到目录。
     *
     * @param srcFile       the file to be moved
     * @param destDir       the destination file
     * @param createDestDir If {@code true} create the destination directory,
     *                      otherwise if {@code false} throw an IOException
     * @throws NullPointerException if source or destination is {@code null}
     * @throws FileExistsException  if the destination file exists
     * @throws IOException          if source or destination is invalid
     * @throws IOException          if an IO error occurs moving the file
     * @since 1.4
     */
    public static void moveFileToDirectory(final File srcFile, final File destDir, final boolean createDestDir)
            throws IOException {
    	FileUtils.moveFileToDirectory(srcFile, destDir, createDestDir);
    }

    /**
     * 将文件或目录移动到目标目录。
当目标位于另一个文件系统上时，请执行“复制并删除”。
     *
     * @param src           the file or directory to be moved
     * @param destDir       the destination directory
     * @param createDestDir If {@code true} create the destination directory,
     *                      otherwise if {@code false} throw an IOException
     * @throws NullPointerException if source or destination is {@code null}
     * @throws FileExistsException  if the directory or file exists in the destination directory
     * @throws IOException          if source or destination is invalid
     * @throws IOException          if an IO error occurs moving the file
     * @since 1.4
     */
    public static void moveToDirectory(final File src, final File destDir, final boolean createDestDir)
            throws IOException {
    	FileUtils.moveToDirectory(src, destDir, createDestDir);
    }

    /**
     * 确定指定文件是符号链接而不是实际文件。
如果路径中的任何位置存在符号链接，则只有在特定文件为。时才返回true。

当使用jdk1.7时，这个方法委托给boolean java.nio.file.Files.isSymbolicLink(Path path) 注意：当前的实现总是返回，false如果运行在jkd1.6上，并且系统被检测为Windows使用FilenameUtils.isSystemWindows()

对于在Java 1.7或更高版本上运行的代码，请改为使用以下方法： 
boolean java.nio.file.Files.isSymbolicLink(Path path)
     * @param file the file to check
     * @return true if the file is a Symbolic Link
     * @throws IOException if an IO error occurs while checking the file
     * @since 2.0
     */
    public static boolean isSymlink(final File file) throws IOException {
    	return FileUtils.isSymlink(file);
    }
    
}

